package com.mldong.aop;

import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.mldong.annotation.DataScope;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 控制数据权限插件的行为：
 * - 默认所有 Mapper 查询都不启用数据权限
 * - 加了 @DataScope 注解的方法/类，才启用数据权限逻辑
 */
@Aspect
@Component
public class DataPermissionAop {

    /**
     * 拦截所有 Mapper 方法
     */
    @Around("target(com.baomidou.mybatisplus.core.mapper.BaseMapper)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = getMethodFrom(joinPoint);
        Class<?> targetClass = method.getDeclaringClass();

        // 获取类和方法上的 @DataScope 注解
        DataScope classAnnotation = targetClass.getAnnotation(DataScope.class);
        DataScope methodAnnotation = method.getAnnotation(DataScope.class);

        boolean isClassAnnotated = classAnnotation != null;
        boolean isMethodAnnotated = methodAnnotation != null;

        // 判断是否需要启用数据权限逻辑
        if (isClassAnnotated || isMethodAnnotated) {
            // 如果是方法单独设置 ignore=true，则忽略数据权限
            if (isMethodAnnotated && methodAnnotation.ignore()) {
                return handleWithIgnore(joinPoint); // 显式忽略
            }

            // 启用数据权限 → 不做任何 Ignore 处理，让 MyBatis Plus 插件生效
            return joinPoint.proceed();
        } else {
            // 没有任何注解 → 默认忽略数据权限
            return handleWithIgnore(joinPoint);
        }
    }

    /**
     * 带有 try-finally 的统一忽略策略处理
     */
    private Object handleWithIgnore(ProceedingJoinPoint joinPoint) throws Throwable {
        IgnoreStrategy strategy = IgnoreStrategy.builder().dataPermission(true).build();
        InterceptorIgnoreHelper.handle(strategy);
        try {
            return joinPoint.proceed();
        } finally {
            InterceptorIgnoreHelper.clearIgnoreStrategy();
        }
    }

    /**
     * 从 JoinPoint 中提取出当前执行的方法对象
     */
    private Method getMethodFrom(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        return signature.getMethod();
    }
}
